/**

This file is part of MaCI/GIMnet.

MaCI/GIMnet is free software: you can redistribute it and/or modify it 
under the terms of the GNU Lesser General Public License as published 
by the Free Software Foundation, either version 3 of the License, or 
(at your option) any later version.

MaCI/GIMnet is distributed in the hope that it will be useful, but WITHOUT 
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public 
License for more details.

You should have received a copy of the GNU Lesser General Public 
License along with GIMnet. (See COPYING.LESSER) If not, see 
<http://www.gnu.org/licenses/>.

**/
#ifndef TGIMI_JPEG_DATA_WITH_TIMESTAMP_H_
#define TGIMI_JPEG_DATA_WITH_TIMESTAMP_H_

#include <string.h>
#include <assert.h>
#include <time.h>
#include <sys/time.h>
#include <inttypes.h>

/**
* This is the jpeg with timestamp data definition
*
* The data contains jpeg image + timestamp
*
* #define GIMI_PROTOCOL_JPEG_WITH_TIMESTAMP		  (GIMI_ID_MIN + 3)

TGIMI_JPEG_data_with_timestamp img;

*/
#ifndef GIM_TIMESTAMP_DEFINED
#define GIM_TIMESTAMP_DEFINED
struct gim_timestamp{
	int32_t tv_sec;	   /* seconds */
	int32_t tv_usec;  /* microseconds */
};
#endif


struct TGIMI_JPEG_data_with_timestamp_header{
public:
	gim_timestamp tim;   ///< The timestamp for the image
	int32_t datasize;			///< Size of the jpeg data in bytes
	
	
};

#define TGIMI_JPEG_data_with_timestamp_header_size (4+4+4)

struct TGIMI_JPEG_data_with_timestamp{
private:
  TGIMI_JPEG_data_with_timestamp(const TGIMI_JPEG_data_with_timestamp &)
    : dataBufferSize(0), 
      data(NULL),
      header(NULL),
      jpgData(NULL) {}
  TGIMI_JPEG_data_with_timestamp &operator=(const TGIMI_JPEG_data_with_timestamp &) { return *this; }
	int32_t dataBufferSize;	///< size of memory reserved for the *data
	unsigned char *data;	///< The whole data

	/*
	* reserves the *data 
	*/
	void allocate(int jpegdatasize){
		if (dataBufferSize < jpegdatasize+TGIMI_JPEG_data_with_timestamp_header_size) {
	  	  if (data) free(data);
		  data = (unsigned char *) malloc((sizeof(unsigned char)*jpegdatasize + TGIMI_JPEG_data_with_timestamp_header_size ));				
		  header = (TGIMI_JPEG_data_with_timestamp_header *) data;
		  jpgData = (unsigned char *) (header+1);
		  dataBufferSize = jpegdatasize + TGIMI_JPEG_data_with_timestamp_header_size;
		  //fprintf(stderr,"JPEG Alloc: dataBufferSize=%d, header=%d, jpegData=%d\n",dataBufferSize, TGIMI_JPEG_data_with_timestamp_header_size, jpegdatasize);
	    }
	}
	
public:
	TGIMI_JPEG_data_with_timestamp_header *header;
	unsigned char *jpgData;
	
	TGIMI_JPEG_data_with_timestamp():
		dataBufferSize(0), 
		data(NULL),
		header(NULL),
		jpgData(NULL) {
	}
	
	~TGIMI_JPEG_data_with_timestamp(){
		if(data) free(data);
	}
	

	/**
	* Copy the jpeg data into *data
	*/
	void setJPEGData(unsigned char *img, int size, struct timeval timestamp){
		allocate(size);
		memcpy(jpgData, img, size);
		header->datasize = size;
		header->tim.tv_sec = (int32_t) timestamp.tv_sec;
		header->tim.tv_usec = (int32_t) timestamp.tv_usec;
		
		//fprintf(stderr,"setJPEGData:: jpegSize=%d (header=%d)\n",size,header->datasize);	
	}
	
	/**
	* Copies the data from the GIMI properly to the structure
	*/
	void handleNetPacket(const unsigned char *indata, int inDataSize){

	  TGIMI_JPEG_data_with_timestamp_header *hdr = 
	  	(TGIMI_JPEG_data_with_timestamp_header *)indata;
	  
	  assert(inDataSize>=TGIMI_JPEG_data_with_timestamp_header_size );
	  
	  //fprintf(stderr,"header: %d data: %d\n",(hdr->datasize+TGIMI_JPEG_data_with_timestamp_header_size), inDataSize);
	  
	  assert((hdr->datasize+TGIMI_JPEG_data_with_timestamp_header_size) ==  inDataSize);
	  
	  allocate(hdr->datasize); // By jpegsize
	  memcpy(data, indata, hdr->datasize+TGIMI_JPEG_data_with_timestamp_header_size); 
	}
	
	/**
	* Returns the size of the whole data in bytes
	*/
	int size(){
		return (TGIMI_JPEG_data_with_timestamp_header_size + header->datasize);
	}
	/**
	* Returns pointer to the whole data
	*/
	const unsigned char * getNetPacket(){
	  return data;
	}
	/**
	* Returns the timestamp of the image
	*/
	struct timeval getTimestamp(){
		struct timeval t;
		t.tv_usec = header->tim.tv_usec;
		t.tv_sec = header->tim.tv_sec;
		return t;
	}
	
};


#endif
